package com.godenwater.recv.service;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;

import cn.gov.mwr.szy206.IMessageBody;
import cn.gov.mwr.szy206.IMessageHeader;
import cn.gov.mwr.szy206.SzyBuilder;
import cn.gov.mwr.szy206.SzyParser;
import cn.gov.mwr.szy206.data.BaseData;
import cn.gov.mwr.szy206.utils.ByteUtil;

import com.godenwater.core.spring.Application;
import com.godenwater.core.spring.BaseDao;
import com.godenwater.recv.model.CommonMessage;
import com.godenwater.recv.server.sl651.HydroConfig;
import com.godenwater.recv.utils.FileUtil;

/**
 * 1.1报文消费者
 *
 * @author lipujun
 * @ClassName: MessageConsumer
 * @Description: 通过线程的方式将“报文”解析，然后入库，这是消息进行处理的第一个环节
 * <p>
 * 注意：只启动一个消费者
 * @date Mar 14, 2013
 */
public class MessageSzy206Consumer extends AbstractMessageConsumer implements Runnable {

    private static Logger logger = LoggerFactory
            .getLogger(MessageSzy206Consumer.class);

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    SimpleDateFormat sdfDay = new SimpleDateFormat("yyyyMMdd");

    private static long DAY = 24 * 60 * 60 * 1000;

    private static long HOUR = 60 * 60 * 1000;

    private RedisTemplate redisTemplate;

    private static String KEY = "messages";

    private BaseDao dao = (BaseDao) Application.getInstance()
            .getBean("baseDao");

    public MessageSzy206Consumer() {

    }

    @Override
    public void run() {
        int i = 0;
//		redisTemplate = (RedisTemplate) Application.getInstance().getCtx()
//				.getBean("redisTemplate");
//		//
//		long s = System.currentTimeMillis();
//		while (true) {
//
//			CommonMessage cm = (CommonMessage) redisTemplate.opsForList()
//					.rightPop(Constant.SZY206 + "_" + KEY);
//
//			if (i == 0)
//				s = System.currentTimeMillis();
//
//			if (cm != null) {
//				System.out.println(">> num " + (i++) + " t= "
//						+ (System.currentTimeMillis() - s) / 1000);
//				try {
//					process(cm);
//				} catch (Exception e) {
//					logger.error("原始报文处理线程出现异常：" + e.getMessage());
//					e.printStackTrace();
//				}
//			} else {
//				try {
//					Thread.sleep(100);
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//
//		}

    }

    /**
     * 处理业务逻辑
     * <p>
     * 第一步：原始报文入库
     * <p>
     * 第二步：判断单报、多报。单报写“入库队列”；多报写文件，并根据最后一条报文写“合并队列”
     *
     * @param message
     */
    public void process(String channel, CommonMessage message) throws Exception {
        logger.info("水资源协议原始报文开始处理 > ");

        // SzyServer.getInstance().getLogManager().addLog("开始解析报文！");

        boolean crcFlag = true;

        // ----------------------------------------------------------
        byte[] data = message.getContent();
        BaseData bd = SzyParser.parseMessageBody(data);

        String stcd = bd.getStcd();
        int serial = Integer.parseInt(sdfDay.format(new Date()));
        int amount = bd.getAmount();
        int seq = bd.getSeq();

        // 更新最后活动时间
        //this.writeMessageNew(stcd, channel, bd.getFunc(), bd.getViewtime());

        // 需要根据发送的情况来解析BODY，如果是0xC0，则只需解析相应的时间
        if (StringUtils.equalsIgnoreCase(bd.getFunc(), "C0")) {
            // 因考虑到链接报数据频繁，则只将链路报以外的原始报文入库

            // 写入原始报文库
            String msgstr = SzyBuilder.toHexString((IMessageHeader) message
                    .getHeader())
                    + ByteUtil.toHexString(data)
                    + ByteUtil.toHexString(message.getCRC())
                    + ByteUtil.toHexString(message.getEOF());

            String id = UUID.randomUUID().toString();

            this.writeRtuMessage(id, bd.getStcd(), "SZY206", channel, bd.getFunc(), serial,
                    bd.getViewtime(), amount, seq, msgstr, crcFlag, "", "", 0, 0);


            //在些需要考虑，将数据直接入库的一个数据。


            if (amount == 0) {

                // 单报文，直接进入“入库报文消息队列”
                // Serial2Body serial2body = new Serial2Body();
                // serial2body.setBody(body);
                // serial2body.setSerial(id);
                // serial2body.setFunccode(new byte[] { funcCode });
                // this.server.queueDatabasePush(serial2body);

                System.out.println(">> 单报文，完成进入“入库报文消息队列”！");

            } else {
                // Symbol.SYN 多报文，需组合报文再解析
                // ----1.1查看是不是最后一条报文，如果是，则放入“合并报文消息队列”;如果不是，则进行文件缓存

                // 先将写入文件
                System.out.println(" HydroConfig.getPicTempPath() "
                        + HydroConfig.getPicTempPath());

                String dirPath = HydroConfig.getPicTempPath() + "/" + stcd
                        + "/";
                File dir = new File(dirPath);
                if (!dir.exists()) {
                    dir.mkdirs();
                } else {
                    if (!dir.isDirectory()) {
                        dir.mkdirs();
                    }
                }

                String fileName = dirPath + "/" + serial + "_" + amount + "_"
                        + seq + ".ser";

                // FileUtil.writeObject((SzyMessageBody) body, fileName);

                if (amount == seq) {
                    // 再放入“合并队列”
                    logger.info("放入“合并队列”");
                    // this.server.queueCombinPush(message);
                }
            }
        }
    }


    public static void main(String[] arg) {
        String dirName = "c:\\rcvtemp\\";
        List<File> files = Arrays.asList(new File(dirName).listFiles());
        Collections.sort(files, new Comparator<File>() {
            @Override
            public int compare(File s1, File s2) {
                if (returnDouble(s1) < returnDouble(s2))
                    return -1;
                else if (returnDouble(s1) > returnDouble(s2))
                    return 1;
                else
                    return 0;
            }

            public double returnDouble(File file) {
                String fileName = file.getName();
                int lastPos = fileName.lastIndexOf(".");
                fileName = fileName.substring(0, lastPos);
                if (fileName.indexOf("_") != -1) {
                    String[] fn = fileName.split("_");

                    return Double.parseDouble(fn[fn.length - 1]);
                } else {
                    return 0;
                }

            }

        });

        String newFile = "c:\\aaa.gif";

        MessageSzy206Consumer xxx = new MessageSzy206Consumer();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(new File("c:" + File.separator
                    + "rtu_recv.jpg"), false);

            for (File f : files) {
                System.out.println("f.getname " + f.getName());
                IMessageBody body = (IMessageBody) FileUtil.readObject(f
                        .getPath());
                try {
                    // Up30Body body30 = new HexParser().parse30Body(body);
                    //
                    // List<DataItem> items = body30.getItems();
                    // for (DataItem item : items) {
                    // out.write(item.getValue());
                    // }

                } catch (Exception e) {
                    e.printStackTrace();
                }

                // System.out.println(f.getPath() + File.separator +
                // f.getName());
            }

        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
}
